import os
from typing import Generic, Sequence, Any, Optional, Type

from fastapi import UploadFile, HTTPException
from fastapi.responses import StreamingResponse

from app.core.generic_types import SQLModelType, CreateSchemaType, UpdateSchemaType, ExportSchemaType
from app.deps.crud_deps import CRUDType
from app.models.base import IdType
from app.schemas.query_schema import BaseQueryIn
from app.schemas.result_schema import ResultModel, ResultFormat, PageModel
from app.schemas.user_schema import CurrentUser

ALLOWED_EXTENSIONS = {".xlsx", ".csv"}
ALLOWED_CONTENT_TYPES = ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "text/csv"]

class BaseController(Generic[CRUDType,SQLModelType,CreateSchemaType,UpdateSchemaType]):
    def __init__(self,crud:CRUDType,current_user:Optional[CurrentUser]=None):
        self._crud = crud
        self._current_user = current_user

    @property
    def crud(self)->CRUDType:
        if self._crud is None:
            raise ValueError("CRUD服务没有注入")
        return self._crud

    @property
    def current_user(self) -> CurrentUser:
        if self._current_user is None:
            raise ValueError("没有找到当前用户")
        return self._current_user

    async def get_all(self, query_in: BaseQueryIn) -> ResultModel[Sequence[SQLModelType]]:
        result = await self.crud.get_all(query_in=query_in)
        return ResultFormat.result_list_model(data=result)

    async def get_page(self, current_page: int, page_size: int, query_in: BaseQueryIn, ) -> ResultModel[PageModel[SQLModelType]]:
        result = await self.crud.get_page(current_page=current_page, page_size=page_size, query_in=query_in)
        return ResultFormat.result_page_model(data=result)

    async def get_by_id(self, id: IdType) -> ResultModel[SQLModelType]:
        result = await self.crud.get_by_id(id=id)
        return ResultFormat.result_model(data=result)

    async def get_by_ids(self, ids: Sequence[IdType]) -> ResultModel[Sequence[SQLModelType]]:
        result = await self.crud.get_by_ids(ids=ids)
        return ResultFormat.result_list_model(data=result)

    async def batch_export(self,model:Type[ExportSchemaType],ids:Sequence[IdType],export_name:str="默认") -> StreamingResponse:
        return await self.crud.batch_export(model=model,ids=ids,export_name=export_name)

    async def export_template(self,model:Type[ExportSchemaType],export_name:str="默认") -> StreamingResponse:
        return await self.crud.export_template(model=model,export_name=export_name)

    async def batch_import(self,model:Type[CreateSchemaType],file:UploadFile) -> ResultModel[bool]:
        file_ext = os.path.splitext(file.filename)[1].lower()
        if file_ext not in ALLOWED_EXTENSIONS or file.content_type not in ALLOWED_CONTENT_TYPES:
            raise HTTPException(status_code=400, detail="只允许上传有效的Excel或CSV文件")
        result = await self.crud.batch_import(model=model,file=file)
        return ResultFormat.result_bool(data=result, model_name="批量导入")

    async def create(self, obj: CreateSchemaType) -> ResultModel[bool]:
        result = await self.crud.create(obj=obj)
        return ResultFormat.result_bool(data=result, model_name="添加")

    async def batch_create(self, objs: Sequence[CreateSchemaType]) -> ResultModel[bool]:
        result = await self.crud.batch_create(objs=objs)
        return ResultFormat.result_bool(data=result, model_name="批量添加")

    async def update(self, obj: UpdateSchemaType) -> ResultModel[bool]:
        result = await self.crud.update(obj=obj)
        return ResultFormat.result_bool(data=result, model_name="更新")

    async def update_field(self,id: IdType, field_name: str, field_value: Any,model_name:str="更新字段") -> ResultModel[bool]:
        result = await self.crud.update_field(id=id, field_name=field_name, field_value=field_value)
        return ResultFormat.result_bool(data=result, model_name=model_name)

    async def delete(self, id: IdType) -> ResultModel[bool]:
        result = await self.crud.delete(id=id)
        return ResultFormat.result_bool(data=result, model_name="删除")

    async def batch_delete(self, ids: Sequence[IdType]) -> ResultModel[bool]:
        result = await self.crud.batch_delete(ids=ids)
        return ResultFormat.result_bool(data=result, model_name="批量删除")